package cn.weiron.fun.infrastructure;


import cn.weiron.fun.infrastructure.auth.AuthorityAccountNotExistException;
import cn.weiron.fun.infrastructure.auth.AuthorityAddressErrorException;
import cn.weiron.fun.infrastructure.auth.AuthorityFailureException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * <p>基础设施：异常处理</p>
 *
 * @author 马强
 */
@RestControllerAdvice
@Order(10)
public class GlobalExceptionHandler {
    /**
     * log
     */
    private final Logger logger= LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 200 - 请求参数校验错误
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public ErrorResponse constraintViolationException(
            HttpServletRequest request, ConstraintViolationException exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.BAD_REQUEST,exception);
    }

    /**
     * 200 - 请求参数校验错误
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public ErrorResponse missingServletRequestParameterException(
            HttpServletRequest request, MissingServletRequestParameterException exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.BAD_REQUEST,exception);
    }

    /**
     * 200 - 请求参数校验错误
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public ErrorResponse bindException(
            HttpServletRequest request, BindException exception)
    {
        logger.error(exception.getMessage(),exception);
        List<ObjectError> list=exception.getBindingResult().getAllErrors();
        return list.isEmpty()
                ?ErrorResponse.of(request,HttpStatus.BAD_REQUEST,exception)
                :ErrorResponse.of(request,HttpStatus.BAD_REQUEST,exception,list.get(0).getDefaultMessage());
    }

    /**
     * 203 - 登录过期
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(AuthorityAccountNotExistException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ErrorResponse authorityAccountNotExistException(
            HttpServletRequest request, AuthorityAccountNotExistException exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.UNAUTHORIZED,exception);
    }

    /**
     * 203 - 无权限
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(AuthorityFailureException.class)
    @ResponseStatus(HttpStatus.NON_AUTHORITATIVE_INFORMATION)
    public ErrorResponse authorityFailureException(
            HttpServletRequest request, AuthorityFailureException exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.NON_AUTHORITATIVE_INFORMATION,exception);
    }

    /**
     * 404 - 方法或地址错误
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(AuthorityAddressErrorException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse authorityAddressErrorException(
            HttpServletRequest request, AuthorityAddressErrorException exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.NOT_FOUND,exception);
    }

    /**
     * 500 - 系统错误
     *
     * @param exception the exception object
     * @return object response object after wrapped
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public ErrorResponse missingServletRequestParameterException(
            HttpServletRequest request, Exception exception)
    {
        logger.error(exception.getMessage(),exception);
        return ErrorResponse.of(request,HttpStatus.INTERNAL_SERVER_ERROR,exception);
    }
}